package com.hmy.finance.service.core.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmy.finance.common.enums.PaymentStatusEnum;
import com.hmy.finance.dal.mapper.ContractDailyBillMapper;
import com.hmy.finance.dal.mapper.ProfitLossRecordMapper;
import com.hmy.finance.dal.po.ContractDailyBillPo;
import com.hmy.finance.service.core.IContractDailyBillService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author songkf
 * @description 针对表【contract_daily_bill(合同日费用流水)】的数据库操作Service实现
 * @createDate 2024-02-21 18:55:01
 */
@Service
public class ContractDailyBillServiceImpl extends ServiceImpl<ContractDailyBillMapper, ContractDailyBillPo>
        implements IContractDailyBillService {

    @Resource
    private ProfitLossRecordMapper profitLossRecordMapper;

    @Override
    public ContractDailyBillPo queryContractDailyBillByContractIdWithDate(Long contractId, LocalDate handleDate) {
        LocalDateTime startOfDay = handleDate.atStartOfDay();
        // 将 LocalDateTime 转换为 Timestamp
        Timestamp startTimestamp = Timestamp.valueOf(startOfDay);
        // 计算结束时间（下一天的开始时间，即不包含当天）
        LocalDateTime nextDayStart = handleDate.atTime(LocalTime.MAX);
        // 将结束时间转换为 Timestamp
        Timestamp endTimestamp = Timestamp.valueOf(nextDayStart);
        return this.baseMapper.selectOne(Wrappers.<ContractDailyBillPo>lambdaQuery()
                .eq(ContractDailyBillPo::getContractId, contractId)
                .between(ContractDailyBillPo::getFeeIncurredTime, startTimestamp, endTimestamp)
        );
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean clearContractDailyBill(Long contractId, LocalDate localDate) {
        LocalDateTime startOfDay = localDate.atStartOfDay();
        List<ContractDailyBillPo> list = this.baseMapper.selectList(Wrappers.<ContractDailyBillPo>lambdaQuery()
                .eq(ContractDailyBillPo::getContractId, contractId)
                .between(ContractDailyBillPo::getFeeIncurredTime, startOfDay, LocalDate.now().atTime(LocalTime.MAX)));
        if (this.baseMapper.delete(Wrappers.<ContractDailyBillPo>lambdaQuery()
                .eq(ContractDailyBillPo::getContractId, contractId)
                .between(ContractDailyBillPo::getFeeIncurredTime, startOfDay, LocalDate.now().atTime(LocalTime.MAX))) > 0) {
            List<Long> profitLossList = new ArrayList<>();
            list.forEach(item -> {
                item.getProfitLossInfo().forEach(profitLoss -> {
                    profitLossList.add(profitLoss.getRecordId());
                });
            });
            if (!profitLossList.isEmpty()) {
                profitLossRecordMapper.batchWaitEffectiveProfitLossById(profitLossList);
            }
        }
        return true;
    }

    @Override
    public List<ContractDailyBillPo> queryContractDailyBillListByContractIdAndDateArea(Long contractId, LocalDate localDate, LocalDate now) {
        LocalDateTime startOfDay = localDate.atStartOfDay();
        LocalDateTime endOfDay = now.atTime(LocalTime.MAX);
        return this.baseMapper.selectList(Wrappers.<ContractDailyBillPo>lambdaQuery()
                .eq(ContractDailyBillPo::getContractId, contractId)
                .between(ContractDailyBillPo::getFeeIncurredTime, startOfDay, endOfDay));
    }

    @Override
    public List<ContractDailyBillPo> selectWaitOffsetList(Long customerId, Long contractId, LocalDate startDate, LocalDate endDate) {
        //Build the lambda query wrapper
        LambdaQueryWrapper<ContractDailyBillPo> queryWrapper = Wrappers.<ContractDailyBillPo>lambdaQuery()
                .eq(Objects.nonNull(customerId), ContractDailyBillPo::getCustomerId, customerId)
                .eq(Objects.nonNull(contractId), ContractDailyBillPo::getContractId, contractId)
                .ge(Objects.nonNull(startDate), ContractDailyBillPo::getFeeIncurredTime, Timestamp.valueOf(startDate.atStartOfDay()))
                .le(Objects.nonNull(endDate), ContractDailyBillPo::getFeeIncurredTime, Timestamp.valueOf(endDate.atTime(LocalTime.MAX)))
                .in(ContractDailyBillPo::getPaymentStatus, PaymentStatusEnum.UNPAID, PaymentStatusEnum.PARTIAL_PAYMENT)
                .orderByAsc(ContractDailyBillPo::getFeeIncurredTime);
        //Return the select result
        return this.baseMapper.selectList(queryWrapper);
    }
}




